
#include "TinyMsgBuffer.h"
namespace TinyCC{
	namespace msg{

		bool CTinyTCPMsg::unPackage( CTinyTCPRawMsg& rawMsg,CTinyMsg* msg )
		{
			if(msg == NULL)
				return false;
			if( rawMsg.m_lDataLength >= sizeof( m_msgHead ) )
			{
				char* pDataCursor = (char*)rawMsg.m_pData;
				char* pDataBody = (char*)rawMsg.m_pData + sizeof( m_msgHead );
				memcpy( (void*)(m_msgHead.MagicKey), rawMsg.m_pData, 4 );
				pDataCursor += 4;

				memcpy( m_msgHead.m_DestINS, pDataCursor, 8 );
				pDataCursor += 8;

				memcpy( m_msgHead.m_SourceINS, pDataCursor, 8 );
				pDataCursor += 8;

				//memcpy( m_msgHead.m_dataType, pDataCursor, 4 );

				DWORD* pDWord = ( DWORD* )pDataCursor;
				m_msgHead.m_dataType = ntohl( *pDWord );
			    pDataCursor += 4;

				//DWORD* pDWord = ( DWORD* )pDataCursor;
				m_msgHead.m_dwMsgLength = ntohl( *pDWord );
				pDataCursor += 4;

				if( m_msgHead.m_dwMsgLength <= (rawMsg.m_lDataLength - sizeof( m_msgHead ) ) )
				{
					if( m_pData != NULL )
					{
						delete[] m_pData;
						m_pData = NULL;
					}
					m_pData = new char[ m_msgHead.m_dwMsgLength ];
					memcpy( m_pData, pDataBody, m_msgHead.m_dwMsgLength );
					m_lDataLength = m_msgHead.m_dwMsgLength;
					msg->deSerialize((char *)m_pData, m_msgHead.m_dwMsgLength);
					char* msgEnd = pDataBody + m_msgHead.m_dwMsgLength;
					if( memcmp( msgEnd, g_MagicEnd, 4 ) == 0 )
					{
						return true;
					}
					//is clear mem needed?
				}
			}
			return false;
		}

		const char* CTinyTCPMsg::package(long &length,CTinyMsg* msg)
		{
			const char * p_serial=NULL;
			p_serial=msg->serialize(m_lDataLength);
			
			m_msgHead.m_dwMsgLength=m_lDataLength;

			if(m_pData !=NULL)
			{
				delete[] m_pData;
				m_pData =NULL;
			}
			m_pData =new char[m_lDataLength];
			memcpy( m_pData, p_serial, m_lDataLength );

			if( m_pData == NULL  )
				return NULL;

			//Calculate the size of memory
			long serializeSize =  sizeof(CTinyTCPMsgHead) + m_msgHead.m_dwMsgLength + sizeof(g_MagicEnd);
			length = serializeSize;

			if(  m_pSerializedData != NULL)
			{
				delete[] m_pSerializedData;
				m_pSerializedData = NULL;
			}
			m_pSerializedData = new char[ serializeSize ];

			char* pCursor = m_pSerializedData;

			memcpy( m_pSerializedData, m_msgHead.MagicKey, 4 );
			pCursor += 4;

			memcpy( pCursor, m_msgHead.m_DestINS, 8 );
			pCursor += 8;

			memcpy( pCursor, m_msgHead.m_SourceINS, 8 );
			pCursor += 8;

			DWORD* pDWord = (DWORD*)pCursor;
			*pDWord = htonl( m_msgHead.m_dataType );
			pCursor += 4;

			//DWORD* pDWord = (DWORD*)pCursor;
			*pDWord = htonl( m_msgHead.m_dwMsgLength );
			pCursor += 4;

			pCursor += 32;

			memcpy( pCursor, m_pData, m_lDataLength );
			pCursor += m_lDataLength;
			memcpy( pCursor, g_MagicEnd, 4 );

			return m_pSerializedData;
		}

		bool CTinyTCPMsg::ParseMsgHead(CTinyTCPMsgHead& head, const char* pMsg, long len)
		{
			if( len >= sizeof( head ) )
			{
				char* pDataCursor = (char*)pMsg;
				memcpy( (void*)(head.MagicKey), pMsg, 4 );
				pDataCursor += 4;

				memcpy( head.m_DestINS, pDataCursor, 8 );
				pDataCursor += 8;

				memcpy( head.m_SourceINS, pDataCursor, 8 );
				pDataCursor += 8;

				DWORD* pDWord = ( DWORD* )pDataCursor;
				head.m_dwMsgLength = ntohl( *pDWord );
				//pDataCursor += 4;

				return true;
			}
			else
			{
				return false;
			}
		}
	}
}